package org.light.simpleauth;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.exception.ValidateException;
import org.light.generator.Generator;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class PasswordUtilGenerator extends Generator{
	protected Domain userDomain;

	public PasswordUtilGenerator(Domain userDomain){
		super();
		this.setUserDomain(userDomain);
		super.fileName = "password_util.rs";
	}

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
	}

	@Override
	public StatementList generateStatementList() throws ValidateException {
		List<Writeable> sList = new ArrayList<Writeable>();
		sList.add(new Statement(1000L,0,"use rand::Rng;"));
		sList.add(new Statement(1000L,0,"use crate::"+this.userDomain.getServiceimplSuffix()+"::init_db;"));

		sList.add(new Statement(2000L,0,"pub async fn generate_salt() -> Result<String, sqlx::Error>{"));
		sList.add(new Statement(3000L,1,"let mut salt = pure_generate_salt().await.unwrap();"));
		sList.add(new Statement(4000L,1,"while unique_salt(salt.clone()).await.unwrap() == false {"));
		sList.add(new Statement(5000L,2,"salt = pure_generate_salt().await.unwrap();"));
		sList.add(new Statement(6000L,1,"}"));
		sList.add(new Statement(7000L,1,"Ok(salt.clone())"));
		sList.add(new Statement(8000L,0,"}"));
		sList.add(new Statement(9000L,0,""));
		sList.add(new Statement(10000L,0,"pub async fn pure_generate_salt() -> Result<String, sqlx::Error>{"));
		sList.add(new Statement(11000L,1,"let mut salt = \"\".to_string();"));
		sList.add(new Statement(12000L,1,"let saltletters = vec!['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];"));
		sList.add(new Statement(13000L,1,"let mut rng = rand::thread_rng();"));
		sList.add(new Statement(14000L,0,""));
		sList.add(new Statement(15000L,1,"for i in 0..32 {"));
		sList.add(new Statement(16000L,2,"let rand_num: usize = rng.gen_range(0..16);"));
		sList.add(new Statement(17000L,2,"salt.push(*saltletters.get(rand_num).unwrap());"));
		sList.add(new Statement(18000L,1,"}"));
		sList.add(new Statement(19000L,1,"Ok(salt)"));
		sList.add(new Statement(20000L,0,"}"));
		sList.add(new Statement(21000L,0,""));
		sList.add(new Statement(22000L,0,"pub async fn unique_salt(salt:String) ->Result<bool, sqlx::Error>{"));
		sList.add(new Statement(23000L,1,"let app_state = init_db();"));
		sList.add(new Statement(24000L,1,"let count = app_state.await.context."+StringUtil.getSnakeName(this.userDomain.getPlural())+".count_salt(salt).await.unwrap().count_num;"));
		sList.add(new Statement(25000L,1,"Ok(count==0)"));
		sList.add(new Statement(26000L,0,"}"));

		return WriteableUtil.merge(sList);
	}
}
